package asem.ast.expresiones;

import java.util.LinkedList;

import alex.Token;
import asem.TablaSimbolos;
import asem.excepciones.ExcepcionLlamadaInvalida;
import asem.excepciones.ExcepcionMetodoInexistente;
import asem.excepciones.ExcepcionSignaturaIncorrecta;
import asem.tablaSimbolos.Metodo;
import asem.tablaSimbolos.Parametro;
import asem.tablaSimbolos.tipo.Tipo;
import asem.tablaSimbolos.tipo.TipoClase;
import asem.tablaSimbolos.tipo.TipoMetodo;

public class NodoLlamadaMetodo extends NodoLlamada {
	protected LinkedList<NodoExpresion> argsActuales;

	public NodoLlamadaMetodo(Token id, LinkedList<NodoExpresion> args,
			NodoLlamadaEncadenada lista) {
		super(id);
		argsActuales = args;
		cadenaId = lista;
	}

	@Override
	public TipoMetodo chequeoSentencias() {
		Metodo m = obtenerMetodo();

		chequeoArgs(m);
		TipoMetodo t = m.getRetorno();

		if (cadenaId != null) {
			if (t instanceof TipoClase)
				t = cadenaId.chequeoSentencias((Tipo) t);
			else
				throw new ExcepcionLlamadaInvalida(t, cadenaId.getId());
		}

		return m.getRetorno();
	}

	protected Metodo obtenerMetodo() {
		Metodo m = TablaSimbolos.tabla.claseActual().getMetodo(
				identificador.getLexema());

		if (m == null)
			throw new ExcepcionMetodoInexistente(TablaSimbolos.tabla
					.claseActual().getNombre(), identificador);

		return m;
	}

	private void chequeoArgs(Metodo met) {
		Tipo t;
		Parametro p;
		int i = 1;
		int f = met.getCantParametros();

		for (NodoExpresion exp : argsActuales) {
			if (i > f)
				throw new ExcepcionSignaturaIncorrecta(met.getIdentificador());

			t = (Tipo) exp.chequeoSentencias();
			p = met.obtenerParametroPosicion(i);

			if (!p.getTipo().compatible(t))
				throw new ExcepcionSignaturaIncorrecta(met.getIdentificador(),
						p, t);

			i++;
		}
	}

}